import {RegexEnum} from 'commons/js/regexEnum';
import {Message} from 'iview';
import router from "../../router";

export const CommonUtils = {
    isEmptyOrNull(v) { // 判断字符串是否为空
        return typeof (v) === 'undefined' || v == '' || v == null ? true : false;
    },
    isObject(v) { // 判断是否为对象
        if (Object.prototype.toString.call(v) == '[object Array]') {
            return false;
        }
        return typeof (v) === 'object' || v != null ? true : false;
    },
    isArray(v) { // 判断是否为数组
        return Object.prototype.toString.call(v) === '[object Array]';
    },
    isNodeList(v) { // 判断是否为节点集
        return Object.prototype.toString.call(v) === '[object NodeList]';
    },
    isInputElement(v) { // 判断是否为input元素
        return Object.prototype.toString.call(v) === '[object HTMLInputElement]';
    },
    isFunction(v) { // 判断是否为函数
        return typeof (v) === 'function';
    },
    isNumber(v) { // 判断是否为整数
        return typeof (v) === 'number';
    },
    isString(v) { // 判断是否为字符串
        return typeof (v) === 'string';
    },
    regValidator(regx, value) {
        /**
         * 正则统一验证函数
         * @param (regex : regex) 正则规则
         * @param (value : Objext) 值
         * @return Boolean
         */
        if (CommonUtils.isEmptyOrNull(regx) || CommonUtils.isEmptyOrNull(value) || CommonUtils.isArray(value)) {
            // throw new Error('参数有误...');
            return false;
        }
        return regx.test(value);
    },   
    /* iview 自定义验证 */
    iviewValidator(rule, value, callback){
        if(typeof value === 'object' && rule.ruleValidate){ //如果值为对象，代表有子级验证， 针对一个prop多个输入框
            for(let key in value){
                if(rule.ruleValidate[key].required && value[key] === ''){	//如果为必选， 且内容为空， 提示错误
                    return callback(rule.ruleValidate[key].message);
                }
                if(rule.ruleValidate[key].reg && !RegexUtils(rule.ruleValidate[key].reg, value[key]) && value[key] !== '' && value[key] !== undefined && value[key] !== null){	//值不为空， 如果有验证规则, 验证不通过，返回验证规则提示
                    return callback(rule.ruleValidate[key].regMessage);
                }
            }
            return callback()
        }

        //如果值不为一个对象，普通验证
        if(rule.required && value === ''){    //如果为必须验证的且值为空，提示错误
            return callback(rule.message)
        }
        
        if(rule.reg && !RegexUtils(rule.reg, value) && value !== '' && value !== undefined && value !== null){ //值不为空， 如果有验证规则, 验证不通过，返回验证规则提示
            rule.message = rule.regMessage;
            return callback(rule.regMessage)
        }

        return callback() // 验证通过
    },  
    /* 判断浏览器是否需要更新 */
    getBrowserVersion(){
        let NV = {
            name: '',
            version: 0
        };    
        let UA = navigator.userAgent.toLowerCase();  

        NV.name = (!!window.ActiveXObject || "ActiveXObject" in window) ? 'ie' : (UA.indexOf('firefox') > 0) ? 'firefox' : 
            (UA.indexOf('chrome') > 0) ? 'chrome' : window.opera ? 'opera' : window.openDatabase ? 'safari' : 'other';

        NV.version = (NV.name == 'firefox') ? UA.match(/firefox\/([\d.]+)/)[1] :    
            (NV.name == 'chrome') ? UA.match(/chrome\/([\d.]+)/)[1] :    
            (NV.name == 'opera') ? UA.match(/opera.([\d.]+)/)[1] :    
            (NV.name == 'safari') ? UA.match(/version\/([\d.]+)/)[1] : '0';

        // console.dir(NV)

        if( (NV.name === 'chrome' && UA.indexOf('se') === -1 && parseInt(NV.version) < 52) || //谷歌
            (NV.name === 'chrome' && UA.indexOf('se') > -1 && parseInt(NV.version) < 49) || //搜狗
            (NV.name === 'firefox' && parseInt(NV.version) < 50) || //火狐
            (NV.name === 'opera' && parseInt(NV.version) < 40) || //欧朋
            (NV.name === 'safari' && parseInt(NV.version) < 35) ||  //safari
            (NV.name === 'other')
        ){
            Storage.setObj('browser', true);
            // return true; //提示更新浏览器
        }

        Storage.setObj('browser', false);
        // return false;    //不提示更新

    },
    toTop(elm, top, time, isClose){       //指定元素， 顶部距离,  时间 ms,  是否是关闭动画

        if(isClose){
            window.cancelAnimationFrame(animate);
            return;
        }; 
        let animate = null;
        if(!elm) return;
        let startTop = elm.scrollTop;                       //开始顶部距离
        let endTop = top;                                   //目标顶部距离
        let distance = endTop - startTop;                   //总距离

        if(distance === 0) return;                          //如果距离为0,没必要继续计算了       

        let step =  Math.floor(time / 16.6);                //总步数    总时间除以 16.6, 16.6相当于一帧的时间
        let yetStep = 0;                                    //已经走过的步数
        let stepDistance = distance > 0 ? Math.floor(distance / step) : Math.ceil(distance / step);     //每步走的距离, distance 为正数 向下取整， distance 为负数 向上取整
        let hasLastStep = distance % step !== 0;            //是否有最后一步 有余数代表需要在最后一步加余数
        
        function start(){
            if(hasLastStep && step === yetStep){            //在最后一步增加余数
                elm.scrollTop = elm.scrollTop + (distance % step);
            }else{
                elm.scrollTop = elm.scrollTop + stepDistance;
            }

            if(yetStep === step) return;                    //如果 已滚动的步数 等于 总步数 不执行后面函数
            
            yetStep++;
            animate = window.requestAnimationFrame(start);
        }
        
        start();
    }                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
};

// 正则工具类
export const RegexUtils = (type,v)=>{
    return CommonUtils.regValidator(RegexEnum[type], v);
};

/* ========================== 对Array的扩展 ============================ */
// 添加元素（含重复）
Array.prototype.add = function (val) {
    if (CommonUtils.isEmptyOrNull(val)) return false;
    this.push(val);
    return true;
}

// 添加元素（去除重复）
Array.prototype.addSet = function (val) {
    if (CommonUtils.isEmptyOrNull(val)) return false;
    for (var i = 0; i < this.length; i++) {
        if (typeof (this[i]) === val) break;
        this[i].push(val);
    }
    return true;
}

// 根据角标删除
Array.prototype.removeByIndex = function (index) {
    return !CommonUtils.isEmptyOrNull(this.splice(index, 1));
}

// 根据值删除
Array.prototype.removeByValue = function (val) {
    for (var i = 0; i < this.length; i++) {
        if (typeof (this[i]) === val) {
            this.splice(i, 1);
            return true;
        }
        return false;
    }
}

// 根据键值对删除
Array.prototype.removeByKey = function (key,val) {
    for (var i = 0; i < this.length; i++) {
        if (this[i][key] === val) {
            this.splice(i, 1);
            break;
        }
    }
}

Array.prototype.indexOf = function(val) {
  for (var i = 0; i < this.length; i++) {
    if (this[i] == val) return i;
  }
  return -1;
};

Array.prototype.removeArray = function(val) {
  var index = this.indexOf(val);
  if (index > -1) {
    this.splice(index, 1);
  }
};

/**
 * 将数据转换成base64
 * @param {any} str
 * @returns
 */
function base64encode(str) {
    var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    var output = "";
    var chr1, chr2, chr3 = "";
    var enc1, enc2, enc3, enc4 = "";
    var i = 0;
    var input = utf16to8(str);
    do {
        chr1 = input.charCodeAt(i++);
        chr2 = input.charCodeAt(i++);
        chr3 = input.charCodeAt(i++);
        enc1 = chr1 >> 2;
        enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
        enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
        enc4 = chr3 & 63;
        if (isNaN(chr2)) {
            enc3 = enc4 = 64;
        } else if (isNaN(chr3)) {
            enc4 = 64;
        }
        output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) + keyStr.charAt(enc3) + keyStr.charAt(enc4);
        chr1 = chr2 = chr3 = "";
        enc1 = enc2 = enc3 = enc4 = "";
    } while (i < input.length);
    return output;

}

/**
 * 本地保存父类
 */
class StorageS {
    constructor(storage) {
        if (!storage) {
            return new Error('当前浏览器不支持本地存储...');
        }
        this.storage = storage;
    }
    setItem(key, value) { // 保存单个字符串
        if (this.storage == null || CommonUtils.isEmptyOrNull(key) || CommonUtils.isEmptyOrNull(value) || !CommonUtils.isString(value)) {
            return;
        }
        this.storage.setItem(key, value);
    }
    getItem(key) { // 获取单个字符串
        if (this.storage == null || CommonUtils.isEmptyOrNull(key)) {
            return null;
        }
        if (CommonUtils.isEmptyOrNull(this.storage.getItem(key))) {
            return null;
        }
        return this.storage.getItem(key);
    }
    setObj(key, value) { // 保存json对象
        if (this.storage == null || CommonUtils.isEmptyOrNull(key) || (CommonUtils.isEmptyOrNull(value) && !CommonUtils.isArray(value))) {
            return;
        }
        if (!CommonUtils.isObject(value) && CommonUtils.isString(value) && !CommonUtils.isArray(value)) {
            this.storage.setItem(key, value);
            return;
        }
        this.storage.setItem(key, JSON.stringify(value));
    }
    getObj(key) { // 获取json对象
        if (this.storage == null || CommonUtils.isEmptyOrNull(key)) {
            return null;
        }
        if (CommonUtils.isEmptyOrNull(this.storage.getItem(key))) {
            return null;
        }
        return JSON.parse(this.storage.getItem(key));
    }
    remove(key) { // 删除本地存储
        if (this.storage == null || CommonUtils.isEmptyOrNull(key)) {
            return true;
        }
        if (CommonUtils.isEmptyOrNull(this.storage.getItem(key))) {
            return true;
        }
        this.storage.removeItem(key);
        if (!CommonUtils.isEmptyOrNull(this.storage.getItem(key))) {
            return false;
        }
        return true;
    }
    clear() {
        this.storage.clear();
    }
}

// 本地存储对象
class LocalStorage extends StorageS {
    constructor() {
        super(window.localStorage);
    }
}
export const Storage = new LocalStorage();

// 会话存储对象
class SessionStorage extends StorageS {
    constructor() {
        super(window.sessionStorage);
    }
}
export const SessionLocal = new SessionStorage();

/**
 * Cookie对象
 * @param {string} name
 * @param {string} value
 * @param {string} time 注意：d 代表天; h 代表小时; m 代表分钟
 * @class CookieStorage
 */
class CookieStorage {
    setCookie(name, value, time) {
        if (CommonUtils.isEmptyOrNull(name) || CommonUtils.isEmptyOrNull(value)) {
            return;
        }
        let date = new Date();
        let times = 0;
        if (time.charAt(0).toLowerCase() === 'd') { // 以天为单位
            times = parseInt(time.substr(1));
            date.setTime(date.getTime() + times * 24 * 60 * 60 * 1000);
        } else if (time.charAt(0).toLowerCase() === 'h') { // 以小时为单位
            times = parseInt(time.substr(1));
            date.setTime(date.getTime() + times * 60 * 60 * 1000);
        }
        document.cookie = name + '=' + escape(value) + ' ;expires=' + date.toGMTString();
    }
    getCookie(name) {
        if (CommonUtils.isEmptyOrNull(name)) {
            return;
        }
        let reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)');
        let arr = document.cookie.match(reg);
        if (!CommonUtils.isArray(arr)) {
            return null;
        }
        return unescape(arr[2]);
    }
    clearCookie(name) {
        let cookie = this.getCookie(name);
        if (CommonUtils.isEmptyOrNull(name) || CommonUtils.isEmptyOrNull(cookie)) {
            return;
        }
        let date = new Date();
        date.setTime(date.getTime() - 1);
        document.cookie = name + '=' + cookie + ' ;expires=' + date.toGMTString();
    }
}
export const Cookie = new CookieStorage();

// 对Date的扩展，将 Date 转化为指定格式的String
// 月(M)、日(d)、小时(h)、分(m)、秒(s)、季度(q) 可以用 1-2 个占位符，
// 年(y)可以用 1-4 个占位符，毫秒(S)只能用 1 个占位符(是 1-3 位的数字)
// 例子：
// (new Date()).Format("yyyy-MM-dd HH:mm:ss.S") ==> 2006-07-02 08:09:04.423
// (new Date()).Format("yyyy-M-d h:m:s.S")      ==> 2006-7-2 8:9:4.18
Date.prototype.Format = function (fmt) {
    var o = {
        "M+": this.getMonth() + 1, //月份
        "d+": this.getDate(), //日
        "H+": this.getHours(), //小时
        "m+": this.getMinutes(), //分
        "s+": this.getSeconds(), //秒
        "q+": Math.floor((this.getMonth() + 3) / 3), //季度
        S: this.getMilliseconds() //毫秒
    };
    if (/(y+)/.test(fmt))
        fmt = fmt.replace(
            RegExp.$1,
            (this.getFullYear() + "").substr(4 - RegExp.$1.length)
        );
    for (var k in o)
        if (new RegExp("(" + k + ")").test(fmt))
            fmt = fmt.replace(
                RegExp.$1,
                RegExp.$1.length == 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length)
            );
    return fmt;
};

//扩展, 获取当月最后一天
Date.prototype.GetLastDay = function () {
    var has31 = [1, 3, 5, 7, 8, 10, 12];
    var nowYear = this.getFullYear();
    var nowMonth = this.getMonth() + 1;
    nowMonth = nowMonth >= 10 ? nowMonth : '0' + nowMonth;
    var nowDay = 0;
    if (nowMonth == 2) {
        if (nowYear % 4 === 0 && nowYear % 100 !== 0) {
            nowDay = 29
        } else {
            nowDay = 28
        }
    } else if (has31.indexOf(Number(nowMonth)) !== -1) {
        nowDay = 31
    } else {
        nowDay = 30
    }
    return nowYear + '/' + nowMonth + '/' + nowDay;
};

//扩展, 获取上n个月第一天
Date.prototype.GetLastMonthFirstDay = function (n) {
  var nowYear = this.getFullYear();
  var nowMonth = this.getMonth();
  if(nowMonth <= n-1) {
    nowYear -= 1;
    nowMonth = 12 - n + nowMonth;
  } else nowMonth -= (n-1)
  nowMonth = nowMonth >= 10 ? nowMonth : '0' + nowMonth;
  return nowYear + '/' + nowMonth + '/' + '01';
};

//扩展, 获取上月最后一天
Date.prototype.GetLastMonthLastDay = function () {
  var has31 = [1, 3, 5, 7, 8, 10, 12];
  var nowYear = this.getFullYear();
  var nowMonth = this.getMonth();
  if(nowMonth == '0') {
    nowYear -= 1;
    nowMonth = 12;
  }
  nowMonth = nowMonth >= 10 ? nowMonth : '0' + nowMonth;
  var nowDay = 0;
  if (nowMonth == 2) {
    if (nowYear % 4 === 0 && nowYear % 100 !== 0) {
      nowDay = 29
    } else {
      nowDay = 28
    }
  } else if (has31.indexOf(Number(nowMonth)) !== -1) {
    nowDay = 31
  } else {
    nowDay = 30
  }
  return nowYear + '/' + nowMonth + '/' + nowDay;
};

// 扩展, 获取本周的开始日期
Date.prototype.GetWeekStartDate = function () {
    var nowDayOfWeek = this.getDay(); //今天本周的第几天
    var nowDay = this.getDate(); //当前日
    var nowMonth = this.getMonth(); //当前月
    var nowYear = this.getFullYear(); //当前年
    var weekStartDate = new Date(nowYear, nowMonth, nowDay - nowDayOfWeek + 1);
    return weekStartDate.Format("yyyy/MM/dd")
};

// 扩展, 获取本周的结束日期
Date.prototype.GetWeekEndDate = function () {
    var nowDayOfWeek = this.getDay(); // 今天本周的第几天
    var nowDay = this.getDate(); // 当前日
    var nowMonth = this.getMonth(); // 当前月
    var nowYear = this.getFullYear(); // 当前年
    var weekEndDate = new Date(nowYear, nowMonth, nowDay + (7 - nowDayOfWeek));
    return weekEndDate.Format('yyyy/MM/dd');
};

// 扩展, 获取上周的开始日期
Date.prototype.GetLastWeekStartDate = function () {
  var nowDayOfWeek = this.getDay(); //今天本周的第几天
  var nowDay = this.getDate(); //当前日
  var nowMonth = this.getMonth(); //当前月
  var nowYear = this.getFullYear(); //当前年
  var weekLastStartDate = new Date(nowYear, nowMonth, nowDay - nowDayOfWeek - 6);
  return weekLastStartDate.Format("yyyy/MM/dd")
};

// 扩展, 获取上周的结束日期
Date.prototype.GetLastWeekEndDate = function () {
  var nowDayOfWeek = this.getDay(); // 今天本周的第几天
  var nowDay = this.getDate(); // 当前日
  var nowMonth = this.getMonth(); // 当前月
  var nowYear = this.getFullYear(); // 当前年
  var weekLastEndDate = new Date(nowYear, nowMonth, nowDay - nowDayOfWeek);
  return weekLastEndDate.Format('yyyy/MM/dd');
};

// 扩展， 获取最近七天
// 2017-04-13 TODO 需完善
// 简化功能
Date.prototype.GetSevenDays = function (type = '') {
    let days = [];
    let nowDay = this.getDate();
    let nowMonth = this.getMonth() + 1;
    let nowYear = this.getFullYear();
    let has31 = [1, 3, 5, 7, 8, 10, 12];

    for (let i = 0; i < 7; ++i) {
        if (nowDay === 0) {
            nowMonth -= 1;
            if (nowMonth === 2) {
                nowDay = nowYear % 4 === 0 && nowYear % 100 !== 0 ? 29 : 28;
            } else {
                nowDay = has31.indexOf(nowMonth) !== -1 ? 31 : 30;
            }
        }
        if (nowMonth === 0) {
            nowYear -= 1;
            nowMonth = 12;
        }
        switch (type) {
            case 'y':
                days.push(`${nowYear}/${nowMonth >= 10 ? nowMonth : '0' + nowMonth}/${nowDay >= 10 ? nowDay : '0' + nowDay}`);
                break;
            case 'm':
                days.push(`${nowMonth >= 10 ? nowMonth : '0' + nowMonth}/${nowDay >= 10 ? nowDay : '0' + nowDay}`);
                break;
            case 'd':
                days.push(`${nowDay >= 10 ? nowDay : '0' + nowDay}`);
                break;
            default:
                days.push(parseInt(nowDay));
                break;
        }
        nowDay -= 1;
    }
    return days.reverse();
};

// 扩展， 按类别获取最近七个
Date.prototype.GetSeven = function (type) {
    let arr = [];
    let nowYear = this.getFullYear();
    let nowMonth = this.getMonth() + 1;
    if (type === 'd') {
        return this.GetSevenDays({
            y: true
        })
    } else if (type === 'm') {
        for (let i = 0; i < 7; ++i) {
            arr.push(`${nowYear}/${nowMonth >= 10 ? nowMonth : '0' + nowMonth}`);
            nowMonth -= 1;
            if (nowMonth === 0) {
                nowMonth = 12;
                nowYear -= 1
            }
        }
    } else if (type === 'y') {
        for (let i = 0; i < 7; ++i) {
            arr.push(`${nowYear}`);
            nowYear -= 1
        }
    }
    return arr.reverse()
}

/***
 * 转换成时间差
 * @param  nTime  时间差(时间戳)
 */
Date.prototype.subtractTime =function (nTime) {
    // var days = Math.floor(nTime / (24 * 3600))
    // var leave1 = nTime % (24 * 3600)    //计算天数后剩余的毫秒数
    var hours = Math.floor(nTime / (3600))
    var leave2 = nTime % (3600)      //计算小时数后剩余的毫秒数
    var minutes = Math.floor(leave2 / (60))
    var leave3 = leave2 % (60)      //计算分钟数后剩余的毫秒数
    var seconds = Math.round(leave3)
    return   hours + "时" + minutes + "分" + seconds + "秒"
}